package graphSample;

import java.util.HashMap;

import core.Entity;
import core.Graph;
import core.Process;

/**
 * TDF 不可中断
 * @author karajan
 *
 */
public class TwoMachineTR extends Thread{
	
	static public Graph getGraph(int n){
		Graph g = new Graph("TwoMachineTR");
		
		// Entities
		Entity p_store = new Entity(g, "p_store");
		p_store.addVariable("$pId","INT");
		p_store.addVariable("$pBId","INT");
		p_store.addVariable("$pATime","DOUBLE");
		
		Entity p_working = new Entity(g, "p_working");
		p_working.addVariable("$pId","INT");
		p_working.addVariable("$pMId","INT");
		
		Entity p_wait = new Entity(g, "p_wait");
		p_wait.addVariable("$pId","INT");
		p_wait.addVariable("$pMId","INT");
		
		Entity m_working = new Entity(g, "m_working");
		m_working.addVariable("$mId","INT");
		m_working.addVariable("$mWTime","DOUBLE");
		m_working.addVariable("$mFTime","DOUBLE");
		
		Entity m_idle = new Entity(g, "m_idle");
		m_idle.addVariable("$mId", "INT");
		m_idle.addVariable("$mATime","DOUBLE");
		m_idle.addVariable("$mFTime","DOUBLE");
		
		Entity m_faild = new Entity(g, "m_faild");
		m_faild.addVariable("$mId", "INT");
		m_faild.addVariable("$mRTime","DOUBLE");
		m_faild.addVariable("$fType","INT");
		
		Entity buffer = new Entity(g, "buffer");
		buffer.addVariable("$bId", "INT");
		buffer.addVariable("$stock", "INT");
		buffer.addVariable("$capacity", "INT");
		buffer.addVariable("$bUTime","DOUBLE");
		
		// Processes
		Process Start = new Process(g, "Start", "$pBId = $bId AND $pBId = $mId AND $mFTime >= $pATime");
		Start.addEntityIn(p_store); Start.addEntityIn(m_idle); Start.addEntityIn(buffer);
		Start.addEntityOut(p_working); Start.addEntityOut(m_working); Start.addEntityOut(buffer);
		Start.addEvalItem("$pMId=$mId");
		Start.addEvalItem("$mWTime=Max[{$pATime,$mATime}]+1");
		Start.addEvalItem("$stock=$stock-1");
		Start.addEvalItem("$bUTime=Max[{$pATime,$mATime}]");
		
		Process Finish = new Process(g, "Finish", "$mWTime <= $mFTime AND $pMId = $mId AND $bId = $pMId +1 And $stock < $capacity");
		Finish.addEntityIn(p_working); Finish.addEntityIn(m_working); Finish.addEntityIn(buffer);
		Finish.addEntityOut(p_store); Finish.addEntityOut(m_idle); Finish.addEntityOut(buffer);
		Finish.addEvalItem("$pBId=$bId");
		Finish.addEvalItem("$pATime=Max[{$mWTime,$bUTime}]");
		Finish.addEvalItem("$mATime=$pATime");
		Finish.addEvalItem("$stock=$stock+1");
		Finish.addEvalItem("$bUTime=$pATime");
		
		Process FailureA = new Process(g, "FailureA", "$mWTime > $mFTime AND $pMId = $mId");
		FailureA.addEntityIn(p_working); FailureA.addEntityIn(m_working);
		FailureA.addEntityOut(p_wait); FailureA.addEntityOut(m_faild);
		FailureA.addEvalItem("$mRTime=$mFTime-Log[RandomReal[]]*2");
		FailureA.addEvalItem("$fType=0");
		
		Process Restart = new Process(g, "Restart", "$pMId = $mId AND $fType=0");
		Restart.addEntityIn(p_wait); Restart.addEntityIn(m_faild);
		Restart.addEntityOut(p_working); Restart.addEntityOut(m_working);
		Restart.addEvalItem("$mWTime=$mRTime+1");
		Restart.addEvalItem("$mFTime=$mRTime-Log[RandomReal[]]*18");

		Process FailureB = new Process(g, "FailureB", "$pBId = $mId AND $mFTime < $pATime");
		FailureB.addEntityIn(p_store); FailureB.addEntityIn(m_idle);
		FailureB.addEntityOut(p_store); FailureB.addEntityOut(m_faild);
		FailureB.addEvalItem("$mRTime=$mFTime-Log[RandomReal[]]*2");
		FailureB.addEvalItem("$fType=1");
		
		Process Recover = new Process(g, "Recover", "$fType=1");
		Recover.addEntityIn(m_faild);
		Recover.addEntityOut(m_idle);
		Recover.addEvalItem("$mATime=$mRTime");
		Recover.addEvalItem("$mFTime=$mRTime-Log[RandomReal[]]*18");
		
		//Add 10000 pieces in p_store
		HashMap<String,String> token;
		for(int i=0;i<10000;i++){
			token = new HashMap<String,String>();
			token.put("$pId", String.valueOf(i));
			token.put("$pBId", "0");
			token.put("$pATime", "0");
			p_store.addToken(token);
		}
		
		//Add 3 buffers in buffer
		for(int i=0;i<3;i++){
			token = new HashMap<String,String>();
			token.put("$bId", String.valueOf(i));
			if(i==0){
				token.put("$stock", "10000");
				token.put("$capacity", "1000000");
			} else if(i==2){
				token.put("$stock", "0");
				token.put("$capacity", "1000000");
			} else {
				token.put("$stock", "0");
				token.put("$capacity", String.valueOf(n));
			}
			
			token.put("$bUTime", "0");
			buffer.addToken(token);
		}
		
		//Add 2 machines in m_idle
		for(int i=0;i<2;i++){
			token = new HashMap<String,String>();
			token.put("$mId", String.valueOf(i));
			token.put("$mATime", "0");
			token.put("$mFTime", String.valueOf(-Math.log(Math.random())*18));
			m_idle.addToken(token);
		}
		
		return g;
	}
}
